1 module targets.android; 2 import features.ldc; 3 import commons; 4 import std.net.curl; 5 import std.path; 6 7 ///This is the one which will be installed when using the SDK. 8 enum TargetAndroidSDK = 35; 9 enum TargetAndroidNDK = "28.0.12433566"; 10 enum TargetJavaJDK = "17.0.12"; 11 ///Use a random Adb Port 12 enum HipremeEngineAdbPort = "55565"; 13 14 private string getAndroidFlagsToolchains() 15 { 16 enum AndroidSDKLibs = 35; 17 18 version(Windows) 19 string system = "windows-x86_64"; 20 else version(linux) 21 string system = "linux-x86_64"; 22 else version(OSX) 23 string system = "darwin-x86_64"; 24 else static assert(false, "Your OS does not support android NDK installation."); 25 26 string toolsPath = buildNormalizedPath(configs["androidNdkPath"].str, "toolchains", "llvm", "prebuilt", system); 27 28 version(Windows) 29 { 30 import std.string:replace; 31 return "-gcc=\""~buildNormalizedPath(toolsPath, "bin/aarch64-linux-android35-clang.cmd").replace("\\", "/") ~"\" " ~ 32 "-linker=\""~buildNormalizedPath(toolsPath, "bin/ld.lld.exe").replace("\\", "/") ~"\" " ~ 33 ///Put the lib path for finding libandroid, liblog, libOpenSLES, libEGL and libGLESv3 34 "-L-L\""~buildNormalizedPath(toolsPath, "sysroot/usr/lib/aarch64-linux-android/"~AndroidSDKLibs~"/").replace("\\", "/")~"\" " 35 ; 36 } 37 else 38 { 39 return "-gcc="~buildNormalizedPath(toolsPath, "bin/aarch64-linux-android35-clang") ~" " ~ 40 "-linker="~buildNormalizedPath(toolsPath, "bin/ld.lld") ~" " ~ 41 "-L-L"~buildNormalizedPath(toolsPath, "sysroot/usr/lib/aarch64-linux-android/"~AndroidSDKLibs~"/") 42 ; 43 } 44 } 45 46 private ChoiceResult runAndroidApplication(ref Terminal t) 47 { 48 version(Windows) 49 { 50 string adb = buildNormalizedPath(configs["androidSdkPath"].str, "platform-tools", "adb.exe"); 51 string gradlew = "gradlew.bat"; 52 } 53 else version(Posix) 54 { 55 string adb = buildNormalizedPath(configs["androidSdkPath"].str, "platform-tools", "adb"); 56 string gradlew = "./gradlew"; 57 58 if(!makeFileExecutable(getHipPath("build", "android", "project", "gradlew"))) 59 { 60 t.writelnError("Could not make gradlew executable."); 61 return ChoiceResult.Error; 62 } 63 } 64 65 with(WorkingDir(getHipPath("build", "android", "project"))) 66 { 67 if(t.wait(spawnShell(gradlew ~ " :app:assembleDebug")) != 0) 68 { 69 t.writelnError("Could not build Java code."); 70 return ChoiceResult.Error; 71 } 72 73 string adbInstall = adb~" install -r "~ 74 buildNormalizedPath(std.file.getcwd(), "app", "build", "outputs", "apk", "debug", "app-debug.apk"); 75 76 t.writeln("Executing adb install: ", adbInstall); 77 t.flush; 78 environment["ANDROID_ADB_SERVER_PORT"] = HipremeEngineAdbPort; 79 if(t.wait(spawnShell(adbInstall)) != 0) 80 { 81 t.writelnError("Could not install application to your device."); 82 return ChoiceResult.Error; 83 } 84 if(t.wait(spawnShell(adb~" shell monkey -p com.hipremeengine.app 1")) != 0) 85 { 86 t.writelnHighlighted("Could not connect to Android's shell"); 87 } 88 } 89 //logcat -b all -v color com.hipremengine.app:D | findstr com.hipremeengine.app 90 return ChoiceResult.Continue; 91 } 92 93 ChoiceResult prepareAndroid(Choice* c, ref Terminal t, ref RealTimeConsoleInput input, in CompilationOptions cOpts) 94 { 95 import features.android_ndk; 96 import features.java_jdk; 97 import features.android_ldc; 98 99 if(!JavaJDKFeature.getFeature(t, input, TargetVersion.parse(TargetJavaJDK))) 100 return ChoiceResult.Error; 101 if(!AndroidNDKFeature.getFeature(t, input, TargetVersion.parse(TargetAndroidNDK))) 102 return ChoiceResult.Error; 103 104 executeGameRelease(t); 105 putResourcesIn(t, getHipPath("build", "android", "project", "app", "src", "main", "assets")); 106 outputTemplate(t, configs["gamePath"].str); 107 108 string ldcLibsPath = getAndroidLDCLibrariesPath.execute(t, input); 109 110 string nextReleaseFlags = "-defaultlib=phobos2-ldc,druntime-ldc " ~ 111 "-link-defaultlib-shared=false " ~ 112 "-L-L"~ ldcLibsPath ~" " ~ 113 "-L-rpath="~ ldcLibsPath~" "; 114 115 environment["DFLAGS"] = nextReleaseFlags ~ getAndroidFlagsToolchains(); 116 t.writeln(environment["DFLAGS"]); 117 t.flush; 118 119 with(WorkingDir(configs["gamePath"].str)) 120 { 121 ProjectDetails proj; 122 if(waitRedub(t, DubArguments().command("build").arch("aarch64--linux-android").configuration("android").opts(cOpts), proj) != 0) 123 { 124 t.writelnError("Compilation failed."); 125 return ChoiceResult.Error; 126 } 127 128 string file = proj.getOutputFile(); 129 if(std.file.exists(file)) 130 { 131 string newName = getHipPath("build", "android", "project", "app", "src", "main", "jniLibs", "arm64-v8a", "libhipreme_engine.so"); 132 t.writelnHighlighted("Renaming ", file, " to "~newName~" for compatibility"); 133 std.file.rename( 134 file, 135 newName 136 ); 137 } 138 } 139 140 return runAndroidApplication(t); 141 }